package com.loe.mvp.util

import android.Manifest
import android.annotation.SuppressLint
import android.app.Activity
import android.app.AlertDialog
import android.content.Context
import android.content.DialogInterface
import android.content.Intent
import android.content.pm.PackageManager
import android.graphics.Color
import android.location.LocationManager
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.os.Environment
import android.os.PowerManager
import android.provider.Settings
import android.util.Log
import android.view.ViewGroup
import androidx.core.content.PermissionChecker
import androidx.fragment.app.FragmentActivity
import com.loe.mvp.ext_java.html

object PermissionUtil
{
    private const val TAG = "PermissionUtil"

    val STORAGE_WRITE = listOf(Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE)

    val STORAGE = listOf(Manifest.permission.READ_EXTERNAL_STORAGE)

    val CAMERA_WRITE_ = listOf(Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.CAMERA)

    val CAMERA = listOf(Manifest.permission.CAMERA)

    val RECORD_WRITE = listOf(Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO)

    val RECORD = listOf(Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO)

    val PHONE = listOf(Manifest.permission.CALL_PHONE)

    val LOCATION = listOf(Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION)

    val LOCATION_BACKGROUND = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)
    {
        listOf(Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_BACKGROUND_LOCATION)
    } else
    {
        LOCATION
    }

    val CONTACTS = listOf(Manifest.permission.READ_CONTACTS)

    val RECORD_SOUND_WRITE = listOf(Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.RECORD_AUDIO)

    val RECORD_SOUND = listOf(Manifest.permission.RECORD_AUDIO)

    fun requestLocation(activity: Activity, onCancel: (() -> Unit)? = null, onPermissionOk: () -> Unit)
    {
        requestForceTip(activity, LOCATION, "位置/定位", "为方便获取您的具体位置，请允许我们访问位置信息权限。", onCancel, onPermissionOk)
    }

    fun requestLocationBackground(activity: Activity, onCancel: (() -> Unit)? = null, onPermissionOk: () -> Unit)
    {
        requestForceTip(activity, LOCATION_BACKGROUND, "位置/定位", "为方便获取您的具体位置，请允许我们访问位置信息权限。", onCancel, onPermissionOk)
    }

    fun requestCamera(activity: Activity, onCancel: (() -> Unit)? = null, onPermissionOk: () -> Unit)
    {
        requestForceTip(activity, CAMERA, "相机", "为方便您拍摄照片，以及进行业务资料的上传，请允许我们访问摄像头。", onCancel, onPermissionOk)
    }

    fun requestRecord(activity: Activity, onCancel: (() -> Unit)? = null, onPermissionOk: () -> Unit)
    {
        requestForceTip(activity, RECORD, "相机和录音", "为方便您拍摄视频，以及进行业务资料的上传，请允许我们访问摄像头和麦克风。", onCancel, onPermissionOk)
    }

    fun requestStorage(activity: Activity, onCancel: (() -> Unit)? = null, onPermissionOk: () -> Unit)
    {
        requestForceTip(activity, STORAGE, "存储", "为方便您访问或修改本地文件，请允许我们访问存储权限。", onCancel, onPermissionOk)
    }

    @JvmStatic
    fun requestForceTip(activity: Activity, permission: List<String>, permissionName: String, tip: String, onCancel: (() -> Unit)? = null, onPermissionOk: (() -> Unit)? = null)
    {
        requestTip(activity, permission, tip, {
            if (it.isNotEmpty())
            {
                showSettingDialog(activity, permission, permissionName, onCancel, onPermissionOk)
            }
        }, onPermissionOk)
    }

    @JvmStatic
    fun requestForce(activity: Activity, permission: List<String>, permissionName: String, onCancel: (() -> Unit)? = null, onPermissionOk: (() -> Unit)? = null)
    {
        request(activity, permission, {
            if (it.isNotEmpty())
            {
                showSettingDialog(activity, permission, permissionName, onCancel, onPermissionOk)
            }
        }, onPermissionOk)
    }

    private fun showSettingDialog(activity: Activity, permission: List<String>, permissionName: String, onCancel: (() -> Unit)? = null, onPermissionOk: (() -> Unit)? = null)
    {
        val builder = AlertDialog.Builder(activity)
        builder.setTitle("缺少“${permissionName}”权限")
        builder.setMessage("<font color='#777777'>请点击 \"设置\"-\"权限\" 打开${permissionName}权限，点击两次后退按钮即可返回。</font>".html)
        builder.setCancelable(false)
        builder.setPositiveButton("设置", null)
        builder.setNegativeButton("取消")
        { dialog, which ->
            dialog.dismiss()
            onCancel?.invoke()
        }
        val dialog = builder.create()
        dialog.show()
        dialog.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener()
        {
            startAppSettings(activity)
            { isOk: Boolean, intent: Intent? ->
                if (isPermissionOk(activity, permission))
                {
                    dialog?.dismiss()
                    onPermissionOk?.invoke()
                }
            }
        }
        dialog.getButton(DialogInterface.BUTTON_NEGATIVE)
            .setTextColor(Color.parseColor("#888888"))
        dialog.getButton(DialogInterface.BUTTON_POSITIVE)
            .setTextColor(Color.parseColor("#5084fe"))
        dialog.window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
    }

    @JvmStatic
    fun request(activity: Activity, permission: List<String>, onPermissionError: ((List<String>) -> Unit)? = null, onPermissionOk: (() -> Unit)? = null)
    {
        try
        {
            if (activity is FragmentActivity)
            {
                if (permission == null || permission.isEmpty())
                {
                    onPermissionOk?.invoke()
                    return
                }
                val deniedPermissions = getDeniedPermissions(activity, permission)
                if (deniedPermissions.isEmpty())
                {
                    onPermissionOk?.invoke()
                    return
                }
                val manager = activity.supportFragmentManager
                var fragment = manager.findFragmentByTag(TAG) as? PermissionFragment
                if (fragment == null)
                {
                    fragment = PermissionFragment()
                    manager.beginTransaction()
                        .add(fragment, TAG)
                        .commitNowAllowingStateLoss()
                }
                fragment.onPermissionOk = onPermissionOk
                fragment.onPermissionError = onPermissionError
                fragment.requestPermissions(deniedPermissions.toTypedArray(), 15)
            } else
            {
                Log.e("Runtime-$TAG", "请传入FragmentActivity")
            }
        }catch (e: Exception)
        {
            Log.e("Runtime-$TAG", e.toString())
        }
    }

    @JvmStatic
    fun requestTip(activity: Activity, permission: List<String>, tip: String, onPermissionError: ((List<String>) -> Unit)? = null, onPermissionOk: (() -> Unit)? = null)
    {
        // 限制提示
        if (!isTip() || tip.isEmpty())
        {
            request(activity, permission, onPermissionError, onPermissionOk)
            return
        }
        if (activity is FragmentActivity)
        {
            if (permission == null || permission.isEmpty())
            {
                onPermissionOk?.invoke()
                return
            }
            val deniedPermissions = getDeniedPermissions(activity, permission)
            if (deniedPermissions.isEmpty())
            {
                onPermissionOk?.invoke()
                return
            }
            PermissionTipDialog(activity)
                .tip(tip)
                .okCallback()
                {
                    val manager = activity.supportFragmentManager
                    var fragment = manager.findFragmentByTag(TAG) as? PermissionFragment
                    if (fragment == null)
                    {
                        fragment = PermissionFragment()
                        manager.beginTransaction()
                            .add(fragment, TAG)
                            .commitNowAllowingStateLoss()
                    }
                    fragment.onPermissionOk = onPermissionOk
                    fragment.onPermissionError = onPermissionError
                    fragment.requestPermissions(deniedPermissions.toTypedArray(), 15)
                }.cancelCallback()
                {
                    onPermissionError?.invoke(listOf())
                }.show()
        } else
        {
            Log.e("Runtime-$TAG", "请传入FragmentActivity")
        }
    }

    private fun getDeniedPermissions(activity: Activity, permissions: List<String>): List<String>
    {
        val list = ArrayList<String>()
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && activity.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.M)
        {
            for (permission in permissions)
            {
                if (activity.checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED)
                {
                    list.add(permission)
                }
            }
        }
        if (list.isEmpty())
        {
            for (permission in permissions)
            {
                if (PermissionChecker.checkSelfPermission(activity, permission) != PermissionChecker.PERMISSION_GRANTED)
                {
                    list.add(permission)
                }
            }
        }
        return list
    }

    class PermissionFragment : androidx.fragment.app.Fragment()
    {
        var onPermissionOk: (() -> Unit)? = null
        var onPermissionError: ((List<String>) -> Unit)? = null

        override fun onCreate(savedInstanceState: Bundle?)
        {
            super.onCreate(savedInstanceState)
            retainInstance = true
        }

        override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray)
        {
            if (requestCode != 15) return

            // android 10
//            if(Build.VERSION.SDK_INT > Build.VERSION_CODES.P)
//            {
            if (isPermissionOk(activity!!, permissions.toList()))
            {
                onPermissionOk?.invoke()
            } else
            {
                onPermissionError?.invoke(permissions.toList())
            }
//            }else
//            {
//                val deniedList = ArrayList<String>()
//                grantResults.forEachIndexed()
//                { i, grant ->
//                    if (grant == PackageManager.PERMISSION_DENIED)
//                    {
//                        deniedList.add(permissions[i])
//                    }
//                }
//                if (deniedList.isEmpty())
//                {
//                    onPermissionOk?.invoke()
//                } else
//                {
//                    onPermissionError?.invoke(deniedList)
//                }
//            }
            onPermissionOk = null
            onPermissionError = null
        }
    }

    /**
     * 忽略电池优化
     */
    @SuppressLint("BatteryLife")
    fun ignoreBatteryOptimizations(context: Context)
    {
        try
        {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
            {
                val isIgnoring: Boolean
                val powerManager = context.getSystemService(Context.POWER_SERVICE) as PowerManager?
                if (powerManager != null)
                {
                    isIgnoring = powerManager.isIgnoringBatteryOptimizations(context.packageName)
                    if (!isIgnoring)
                    {
                        val intent = Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS)
                        intent.data = Uri.parse("package:" + context.packageName)
                        context.startActivity(intent)
                    }
                }
            }
        } catch (e: Exception)
        {
            e.printStackTrace()
        }
    }

    /**
     * 手机是否开启位置服务，如果没有开启那么所有app将不能使用定位功能
     */
    fun isLocationEnable(context: Context): Boolean
    {
        val locationManager = context.getSystemService(Context.LOCATION_SERVICE) as LocationManager
        val gps = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)
        val network = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)
        return gps || network
    }

    /**
     * 判断权限是否完善
     */
    @JvmStatic
    fun isPermissionOk(context: Context, permissions: List<String>): Boolean
    {
        var isOk = true
        permissions.forEach()
        {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
            {
                if (context.checkSelfPermission(it) == PackageManager.PERMISSION_DENIED)
                {
                    isOk = false
                    return@forEach
                }
            }
            if (PermissionChecker.checkSelfPermission(context, it) != PermissionChecker.PERMISSION_GRANTED)
            {
                isOk = false
                return@forEach
            }
        }
        return isOk
    }

    /**
     * 启动应用的设置
     */
    @JvmStatic
    fun startAppSettings(activity: Activity, result: ((isOk: Boolean, Intent?) -> Unit)? = null)
    {
        try
        {
            val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
            intent.data = Uri.parse("package:" + activity.packageName)
            ResultUtil.startResult(activity, intent)
            {
                result?.invoke(it.isOk(), it.data)
            }
        } catch (e: Exception)
        {
            e.printStackTrace()
        }
    }

    /**
     * <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
     */
    fun requestFilePermission(activity: Activity, ok: () -> Unit)
    {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R)
        {
            if (!Environment.isExternalStorageManager())
            {
                UIDialog(activity).title("缺少外部文件访问权限").msg("是否前往设置？").show()
                {
                    val intent = Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION)
                    intent.setData(Uri.parse("package:" + activity.getPackageName()))
                    activity.startResult(intent)
                    {
                        if (Environment.isExternalStorageManager())
                        {
                            ok()
                        }
                    }
                }
            } else
            {
                ok()
            }
        } else
        {
            ok()
        }
    }

    fun isTip(): Boolean
    {
        val cc = (Build.MANUFACTURER + "").toLowerCase();
        return cc.contains("huawei") || cc.contains("honor") || cc.contains("oce") || cc.contains("vivo") || cc.contains("iqoo");
    }
}